package com.liao.myblog.controller.admin;

import com.google.code.kaptcha.impl.DefaultKaptcha;
import com.liao.myblog.enums.ResultCode;
import com.liao.myblog.pojo.Admin;
import com.liao.myblog.service.AdminService;
import com.liao.myblog.service.BlogService;
import com.liao.myblog.service.CatalogueService;
import com.liao.myblog.service.CommentService;
import com.liao.myblog.vo.ResultVO;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.lang.annotation.IncompleteAnnotationException;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@RequestMapping(value = "/admin")
@Controller
public class AdminController {

    @Resource
    private AdminService adminService;

    @Resource
    private BlogService blogService;

    @Resource
    private CatalogueService catalogueService;

    @Resource
    private CommentService commentService;

    @Autowired
    private DefaultKaptcha defaultKaptcha;
    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @RequestMapping(value = {"/", "/index"})
    public String index(HttpServletRequest request) {
        request.setAttribute("path", "index");
        request.setAttribute("blogCount", blogService.findBlogCount());
        request.setAttribute("catalogueCount", catalogueService.findCatalogueCount());
        request.setAttribute("commentCount", commentService.queryCommentCount());
        Admin admin = (Admin) SecurityUtils.getSubject().getPrincipal();
        request.getSession().setAttribute("loginUser", admin);
        return "admin/index";
    }

    @ResponseBody
    @PostMapping(value = "/logins")
    public ResultVO<Object> login(@RequestBody Map<String, Object> map) {
        System.out.println("AdminController.login");
        String userName = (String) map.get("username");
        String password = (String) map.get("password");
        String verifyCode = (String) map.get("verifyCode");
//        Admin admin = adminService.adminLogin(userName, password);
        String loginVerifyCode = redisTemplate.opsForValue().get("loginVerifyCode");
        if (loginVerifyCode == null || loginVerifyCode.length() == 0) {
            return new ResultVO<>(ResultCode.EXPIRED_VERIFYCODE);
//            return ResultUtil.getResult("验证码过期",ResultUtil.RESULT_ERROR);
        }
        if (!loginVerifyCode.equals(verifyCode)) {
            return new ResultVO<>(ResultCode.ERROR_VERIFYCODE);
//            return ResultUtil.getResult("验证码错误",ResultUtil.RESULT_ERROR);
        }

        UsernamePasswordToken token = new UsernamePasswordToken(userName, password);
        Subject subject = SecurityUtils.getSubject();
        try {
            subject.login(token);
            return new ResultVO<>(ResultCode.SUCCESS);
//            return ResultUtil.getResult("成功！", ResultUtil.RESULT_SUCCESS);
        } catch (IncorrectCredentialsException e) {
            return new ResultVO<>(ResultCode.UNEXIST_PASSWORD);
//            return ResultUtil.getResult("密码错误！", ResultUtil.RESULT_ERROR);
        } catch (UnknownAccountException e) {
            return new ResultVO<>(ResultCode.UNEXIST_USERNAME);
//            return ResultUtil.getResult("用户名错误！", ResultUtil.RESULT_ERROR);
        }
    }

    @ResponseBody
    @PostMapping(value = "/kaptcha")
    public ResultVO<Object> kaptcha() throws IOException {
        String text = defaultKaptcha.createText();

        redisTemplate.opsForValue().set("loginVerifyCode", text);
        redisTemplate.expire("loginVerifyCode", 3, TimeUnit.MINUTES);

        BufferedImage image = defaultKaptcha.createImage(text);

        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ImageIO.write(image, "jpg", baos);

        Base64.Encoder encoder = Base64.getEncoder();       //jdk8以上Base64Encoder被弃用

        HashMap<String, Object> map = new HashMap<>();
        map.put("img", encoder.encodeToString(baos.toByteArray()));
//        return ResultUtil.getResult(map, ResultUtil.RESULT_SUCCESS);
        return new ResultVO<>(map);
    }

    @RequiresPermissions(value = "adminMax")
    @ResponseBody
    @RequestMapping(value = "/register")
    public String registerAdmin(String username, String password) {
        SimpleHash name = new SimpleHash("md5", username, null, 2);
        SimpleHash pwd = new SimpleHash("sha-512", password, null, 1024);
        return name + "----------" + pwd;
    }

    @GetMapping(value = {"/login/{id}","/login"})
    public String loginHtml(@PathVariable(required = false, value = "id") Integer id) {
        System.out.println("AdminController.loginHtml");
        System.out.println("=====================");
        System.out.println(id);
        return "admin/login";
    }

    @ResponseBody
    @RequestMapping(value = "/configurations")
    public String configurations(HttpServletRequest request) {
        return "admin/configuration";
    }

    @GetMapping(value = "/profile/index")
    public String profile() {
        return "admin/profile";
    }

    @ResponseBody
    @GetMapping(value = "/profile")
    public ResultVO<Object> profiles() {
        Subject subject = SecurityUtils.getSubject();
        Admin oldAdmin = (Admin) subject.getPrincipal();
        Admin newAdmin = adminService.queryAdmin(oldAdmin.getId());
//        System.out.println(newAdmin);
        if (newAdmin != null) {
            return new ResultVO<>(newAdmin);
//            return ResultUtil.getResult(newAdmin, ResultUtil.RESULT_SUCCESS);
        } else {
            return new ResultVO<>(ResultCode.ERROR);
//            return ResultUtil.getResult("失败", ResultUtil.RESULT_ERROR);
        }
    }

    @ResponseBody
    @PostMapping(value = "/updateName")
    public ResultVO<Object> updateName(@RequestBody Map<String, Object> msg) {
        Subject subject = SecurityUtils.getSubject();
        String username = (String) msg.get("username");
        String nickName = (String) msg.get("nickName");
        Admin admin = (Admin) subject.getPrincipal();
        int i = adminService.updateName(username, nickName, admin.getId());
        if (i > 0) {
            admin.setNickName(nickName);
            admin.setUsername(username);
            return new ResultVO<>(ResultCode.SUCCESS);
//            return ResultUtil.getResult("成功", ResultUtil.RESULT_SUCCESS);
        } else {
            return new ResultVO<>(ResultCode.ERROR);
//            return ResultUtil.getResult("失败", ResultUtil.RESULT_ERROR);
        }
    }

    @ResponseBody
    @PostMapping(value = "/updatePwd")
    public ResultVO<Object> updatePwd(@RequestBody Map<String, Object> msg) {
        Subject subject = SecurityUtils.getSubject();
        String password = (String) msg.get("password");
        String newPassword = (String) msg.get("newPassword");
        Admin admin = (Admin) subject.getPrincipal();
        String pwd = String.valueOf(new SimpleHash("md5", password, null, 2));
        int i = 0;
        String newPwd = null;
        if (pwd.equals(admin.getPassword())) {
            newPwd = String.valueOf(new SimpleHash("md5", newPassword, null, 2));
            i = adminService.updatePwd(admin.getId(), newPwd);
        } else {
            return new ResultVO<>(ResultCode.UNEXIST_OLD_PASSWORD);
//            return ResultUtil.getResult("原密码错误", ResultUtil.RESULT_ERROR);
        }

        if (i > 0) {
            admin.setPassword(newPwd);
            return new ResultVO<>(ResultCode.SUCCESS);
//            return ResultUtil.getResult("成功", ResultUtil.RESULT_SUCCESS);
        } else {
            return new ResultVO<>(ResultCode.ERROR);
//            return ResultUtil.getResult("失败", ResultUtil.RESULT_ERROR);
        }
    }

    @RequestMapping(value = "/logout")
    public String logout() {
        Subject subject = SecurityUtils.getSubject();
        subject.logout();
        return "redirect:/admin/login";
    }
}
